package org.rowan.adi.components.comp2d.polygon;

import java.util.LinkedList;
import org.rowan.adi.components.comp2d.Point2D;
import org.rowan.adi.Vector;

/**
 * The Rectangle class provides functionality for a rectangle in two dimensional
 * space.
 *
 * @author Robert Russell
 * @version 1.0
 */
public class Rectangle extends Polygon {

    private double length; // The length of the rectangle.
    private double width; // The width of the rectangle.

    /**
     * Constructs an instance of Rectangle.
     * @param location the location of the Rectangle.
     * @param width the width of the Rectangle.
     * @param length the length of the Rectangle.
     * @throws IllegalArgumentException the length or the width is not a positive value.
     */
    public Rectangle(Vector location, double width, double length) {
        if (width <= 0) {
            throw new IllegalArgumentException("Invalid width. The width must be a positive value.");
        } else if (length <= 0) {
            throw new IllegalArgumentException("Invalid length. The length must be a positive value.");
        }

        LinkedList<Point2D> points = new LinkedList<Point2D>();
        double x = location.getX();
        double y = location.getY();
        points.add(new Point2D(new Vector(x - (width / 2), y - (length / 2))));
        points.add(new Point2D(new Vector(x - (width / 2), y + (length / 2))));
        points.add(new Point2D(new Vector(x + (width / 2), y + (length / 2))));
        points.add(new Point2D(new Vector(x + (width / 2), y - (length / 2))));

        super.setListofPoints(points);
        super.setLocation(location);
        super.setTrajectory(Vector.ZERO_VECTOR);

        this.length = length;
        this.width = width;
    }

    /**
     * Computes the area of the Rectangle.
     * @return the area of the Rectangle.
     */
    public double computeArea() {
        return length * width;
    }

    /**
     * Gets the length of the Rectangle.
     * @return the length of the Rectangle.
     */
    public double getLength() {
        return this.length;
    }

    /**
     * Gets the width of the Rectangle.
     * @return the width of the Rectangle.
     */
    public double getWidth() {
        return this.width;
    }

    /**
     * Sets the length of the Rectangle to a given value.
     * @param length the new length of the Rectangle.
     * @throws IllegalArgumentException the length is not a positive value.
     */
    public void setLength(double length) {
        if (length <= 0) {
            throw new IllegalArgumentException("Invalid length. The length must be a positive value.");
        }

        this.length = length;
        double x = getLocation().getX();
        double y = getLocation().getY();

        LinkedList<Point2D> points = new LinkedList<Point2D>();
        points.add(new Point2D(new Vector(x - (width / 2), y - (length / 2))));
        points.add(new Point2D(new Vector(x - (width / 2), y + (length / 2))));
        points.add(new Point2D(new Vector(x + (width / 2), y + (length / 2))));
        points.add(new Point2D(new Vector(x + (width / 2), y - (length / 2))));
        super.setListofPoints(points);
    }

    /**
     * Sets the width of the Rectangle to a given value.
     * @param width the new width of the Rectangle.
     * @throws IllegalArgumentException the width is not a positive value.
     */
    public void setWidth(double width) {
        if (width <= 0) {
            throw new IllegalArgumentException("Invalid width. The width must be a positive value.");
        }

        this.width = width;
        double x = getLocation().getX();
        double y = getLocation().getY();

        LinkedList<Point2D> points = new LinkedList<Point2D>();
        points.add(new Point2D(new Vector(x - (width / 2), y - (length / 2))));
        points.add(new Point2D(new Vector(x - (width / 2), y + (length / 2))));
        points.add(new Point2D(new Vector(x + (width / 2), y + (length / 2))));
        points.add(new Point2D(new Vector(x + (width / 2), y - (length / 2))));
        super.setListofPoints(points);
    }
}
